package cn.ronghuanet.org.service.impl;

import cn.ronghuanet.base.service.impl.BaseServiceImpl;
import cn.ronghuanet.org.domain.Department;
import cn.ronghuanet.org.mapper.DepartmentMapper;
import cn.ronghuanet.org.query.DepartmentQuery;
import cn.ronghuanet.org.service.IDepartmentService;
import cn.ronghuanet.base.util.PageList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true,propagation=Propagation.SUPPORTS)
public class DepartmentServiceImpl extends BaseServiceImpl<Department> implements IDepartmentService {
    @Autowired
    private DepartmentMapper departmentMapper;
    //创建redis模板对象
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional //增删改都需要事务
    public void insertOne(Department department) {
        //双删一致性代码
        //1.第一次删除缓存
        redisTemplate.delete("departmentList");
        //处理时间
        Date date = new Date();
        department.setCreateTime(date);
        department.setUpdateTime(date);
        departmentMapper.insertOne(department);
        //直接调用修改,修改层级目录
        updateOne(department);
        //估计一个业务执行的时间
        try {
            Thread.sleep(2000);
            //2.第二次删除缓存
            redisTemplate.delete("departmentList");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional //增删改都需要事务
    public void updateOne(Department department) {
        //1.第一次删除缓存
        redisTemplate.delete("departmentList");
        //1.组合层级目录 /+自己的id  /1
        String myDir="/"+department.getId();
        //2.判断是否有父部门
        if (department.getParentId()!=null){
            Department parent = departmentMapper.getOne(department.getParentId());
            myDir=parent.getDirPath()+myDir;
        }
        //重新给部门层级赋值
        department.setDirPath(myDir);
        //处理时间
        Date date = new Date();
        department.setUpdateTime(date);
        departmentMapper.updateOne(department);
        //估计一个业务执行的时间
        try {
            Thread.sleep(2000);
            //2.第二次删除缓存
            redisTemplate.delete("departmentList");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional //增删改都需要事务
    public void deleteOne(Long id) {
        //1.第一次删除缓存
        redisTemplate.delete("departmentList");
        departmentMapper.deleteOne(id);
        //估计一个业务执行的时间
        try {
            Thread.sleep(2000);
            //2.第二次删除缓存
            redisTemplate.delete("departmentList");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional //增删改都需要事务
    public void patchDel(List<Long> ids) {
        //1.第一次删除缓存
        redisTemplate.delete("departmentList");
        departmentMapper.patchDel(ids);
        //估计一个业务执行的时间
        try {
            Thread.sleep(2000);
            //2.第二次删除缓存
            redisTemplate.delete("departmentList");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Department> loadAll() {
        //缓存方案,采用分布式缓存,redis
        Object departmentList=redisTemplate.opsForValue().get("departmentList");
        //缓存没查到
        if (departmentList==null){
            //redis查询没有值,就在数据库查
            List<Department> list = departmentMapper.loadAll();
            //同步缓存到Redis
            redisTemplate.opsForValue().set("departmentList",list);
            return list;
        }
        return (List<Department>)departmentList;
    }

    @Override
    public List<Department> deptTree(Long id) {
        //业务逻辑
        //1.查询所有的部门
        List<Department> all = loadAll();
        //2.转换当前list得到一个map  key(部门id自己):value(部门对象自己)
        Map<Long, Department> map =
                all.stream().collect(Collectors.toMap(Department::getId, d -> d));
        //3.定义返回的森林(部门树)
        List<Department> tree=new ArrayList<Department>();
        //4.区分一级部门和其他级别部门,其他级别部门找到自己的父部门,把自己放入父部门的children
        for (Department dept:all){
            //如果传入的id是自己就直接跳过,我不把自己装入父部门
            //if (dept.getId().equals(id))continue;
            if (dept.getParentId()==null){
                //一级部门
                tree.add(dept);
            }else {
                //其他级别
                //找到自己的父部门
                Department parent = map.get(dept.getParentId());
                //把自己放入父部门的children
                if (parent!=null){
                    parent.getChildren().add(dept);
                }
            }
        }
        //5.返回部门树
        return tree;
    }
}
